package com.buaa.rental.Util;

import com.buaa.rental.Dao.SequenceID;
import com.buaa.rental.Util.MyAnnotations.AutoIncrement;
import java.lang.reflect.Field;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

@Component
public class SaveMongoEventListener extends AbstractMongoEventListener<Object>
{

	@Autowired
	private MongoTemplate mongoTemplate;

	/**
	 * 在新增记录的时候，回调接口方法，监听文档插入记录的操作，使用反射方法对ID进行自增*
	 */
	@Override
	public void onBeforeConvert(BeforeConvertEvent<Object> event)
	{
		final Object source = event.getSource(); // 获取事件最初发生的对象
		if (source != null)
		{
			// 使用反射工具类，实现回调接口的方法，对成员进行操作
			ReflectionUtils.doWithFields(source.getClass(), field ->
			{
				ReflectionUtils.makeAccessible(field); // 使操作的成员可访问
				AutoIncrement autoIncrement = field.getAnnotation(AutoIncrement.class);
				// 如果是带有@AutoIncrement注解的，成员调用getter方法返回的类型是Number类型的，返回的类型都是0的(没有赋值，默认为0)
				if (autoIncrement != null && field.get(source) instanceof Number
						&& field.getLong(source) == 0)
				{

					String collName =
							source.getClass().getSimpleName().substring(0, 1).toLowerCase()
									+ source.getClass().getSimpleName().substring(1);
					field.set(source, autoIncrement.baseNum() + getNextId(collName));
				}
			});
		}
	}

	/**
	 * 返回下一个自增的ID
	 *
	 * @param collName 集合名称
	 * @return Long 序列值
	 */
	private Long getNextId(String collName)
	{
		Query query = new Query(Criteria.where("collName").is(collName));
		Update update = new Update();
		update.inc("seqId", 1);
		FindAndModifyOptions options = new FindAndModifyOptions();
		options.upsert(true);
		options.returnNew(true);
		SequenceID seq = mongoTemplate.findAndModify(query, update, options, SequenceID.class);
		return seq.getSeqId();
	}
}
